package pl.edu.agh.lab2.sr.gameServer;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;

import pl.edu.agh.lab2.sr.beans.IPlayer;
import pl.edu.agh.lab2.sr.beans.InvalidGameStateException;
import pl.edu.agh.lab2.sr.beans.InvalidUserException;
import pl.edu.agh.lab2.sr.remoteInterfaces.IBattleshipGame;
import pl.edu.agh.lab2.sr.remoteInterfaces.IGameServer;
import pl.edu.agh.lab2.sr.remoteInterfaces.IServerListener;

public class GameServerImpl implements IGameServer {

	private List<IPlayer> registeredPlayers;
	private List<IServerListener> registeredListeners;
	private Object listLock;

	private int gameIdIterator;
	private List<IBattleshipGame> createdGames;

	public GameServerImpl() {
		super();
		registeredPlayers = new ArrayList<IPlayer>();
		registeredListeners = new ArrayList<IServerListener>();
		listLock = new Object();

		gameIdIterator = 0;
		createdGames = new ArrayList<IBattleshipGame>();
	}

	@Override
	public void register(IPlayer player, IServerListener listener)
			throws RemoteException, InvalidUserException {

		String nick = player.getNick();
		synchronized (listLock) {
			if (registeredPlayers.contains(player)) {
				System.err.println("[S] Player already registered: " + nick);
				throw new InvalidUserException("Player already registered: "
						+ nick);
			}

			registeredPlayers.add(player);
			registeredListeners.add(listener);

			System.out.println("[S] registered player: " + nick);
		}
		notifyAllListeners("registered user: " + nick);
	}

	@Override
	public IBattleshipGame createBattleshipGame(IPlayer player1,
			IServerListener listener1, boolean withBot) throws RemoteException,
			InvalidUserException, InvalidGameStateException {

		IBattleshipGame game = null;
		synchronized (listLock) {
			String nick = player1.getNick();
			if (!registeredPlayers.contains(player1)) {
				System.err.println("[S] Player not registered: " + nick);
				throw new InvalidUserException("Player not registered: " + nick);
			}

			synchronized (createdGames) {

				game = new BattleshipGame(player1, listener1, gameIdIterator);

				if (withBot) {
					BattleshipBotPlayer bot = new BattleshipBotPlayer("Bot"
							+ gameIdIterator);
					game.join(bot.getPlayer(), bot.getListener());
					bot.setGame(game);
					Thread botThread = new Thread(bot);
					botThread.start();
					bot.getListener().onServerNotify("[P] You've joined game");
					
				}
				createdGames.add(game);

				listener1.onServerNotify("[P] game created, id: "
						+ gameIdIterator);
				listener1.onServerNotify("[P] You've joined game");
				gameIdIterator++;

			}
		}
		return game;
	}

	@Override
	public IBattleshipGame join(IPlayer player2, IServerListener listener2,
			int gameId) throws RemoteException, InvalidUserException,
			IllegalArgumentException, InvalidGameStateException {

		System.out.println("[S] join");

		if (!isPlayerRegistered(player2)) {
			throw new InvalidUserException("[P] player not registered: "
					+ player2.getNick());
		}

		IBattleshipGame game = null;

		synchronized (createdGames) {
			game = getGameById(gameId);
			game.join(player2, listener2);
		}
		return game;
	}

	@Override
	public List<String> getRegisteredPlayers() throws RemoteException {
		List<String> nicks = new ArrayList<String>();

		synchronized (listLock) {
			for (IPlayer player : registeredPlayers) {
				nicks.add(player.getNick());
			}
		}

		return nicks;
	}

	@Override
	public void quit(IPlayer player, IServerListener listener)
			throws RemoteException, InvalidUserException {
		// TODO Auto-generated method stub

	}

	@Override
	public List<String> getGamesList() throws RemoteException {
		List<String> gamesList = new ArrayList<String>();
		synchronized (createdGames) {
			for (IBattleshipGame game : createdGames) {
				gamesList.add(game.getInfoAboutGame());
			}
		}
		return gamesList;
	}

	private IBattleshipGame getGameById(int gameId) throws RemoteException {
		for (IBattleshipGame game : createdGames) {
			if (game.getId() == gameId) {
				return game;
			}
		}
		throw new IllegalArgumentException("Game does not exist, id: " + gameId);
	}

	private void notifyAllListeners(String msg) throws RemoteException {
		System.out.println("[S] Notifying registered players: " + msg);
		for (IServerListener listener : registeredListeners) {
			listener.onServerNotify(msg);
		}
	}

	private boolean isPlayerRegistered(IPlayer player) {
		boolean isRegistered = false;
		synchronized (listLock) {
			isRegistered = registeredPlayers.contains(player);
		}

		return isRegistered;
	}

}
